package com.server.pool;

import com.core.log.Debug;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

public class ThreadPool extends Object implements Runnable {

    private boolean isRunning;
    private ObjectFIFO idleWorkers;
    private ThreadPoolWorker[] workerList;
    private Vector<PoolElement> taskQueue;
    private int maxThreads;

    public ThreadPool(int maxThreads) {
        // make sure that it's at least one
        this.maxThreads = Math.max(1, maxThreads);
        taskQueue = new Vector<PoolElement>(0);
        idleWorkers = new ObjectFIFO(maxThreads);
//        workerList = new ThreadPoolWorker[maxThreads];
//        for (int i = 0; i < workerList.length; i++) {
//            workerList[i] = new ThreadPoolWorker(idleWorkers);
//        }
    }

    public void start() {
        isRunning = true;
        new Thread(this).start();
    }

    public void putTask(PoolElement task) {
        taskQueue.addElement(task);
        if (isNeedWorker()) {
            ThreadPoolWorker worker = new ThreadPoolWorker(idleWorkers);
            try {
                idleWorkers.add(worker);
            } catch (InterruptedException ex) {
            }
        }
    }

    public boolean isNeedWorker() {
//        Debug.d("worker :" + idleWorkers.getSize());
//        Debug.d("task size :" + taskQueue.size());
        return (idleWorkers.getSize() < maxThreads && idleWorkers.getSize() < taskQueue.size());
    }

    public void execute(PoolElement target) throws InterruptedException {
        // block (forever) until a worker is available
        ThreadPoolWorker worker = (ThreadPoolWorker) idleWorkers.remove();
        worker.process(target);
    }

    public void stopRequestIdleWorkers() {
        try {
            Object[] idle = idleWorkers.removeAll();
            for (int i = 0; i < idle.length; i++) {
                ((ThreadPoolWorker) idle[i]).stopRequest();
            }
        } catch (InterruptedException x) {
            Thread.currentThread().interrupt(); // re-assert
        }
    }

    public void stopRequestAllWorkers() {
        // Stop the idle one's first since that won't interfere with anything
        // productive.
        stopRequestIdleWorkers();

        // give the idle workers a quick chance to die 
        try {
            Thread.sleep(250);
        } catch (InterruptedException x) {
        }

        // Step through the list of ALL workers that are still alive.
        for (int i = 0; i < workerList.length; i++) {
            if (workerList[i].isAlive()) {
                workerList[i].stopRequest();
            }
        }
    }

    @Override
    public void run() {
        while (isRunning) {
            if (!taskQueue.isEmpty()) {
                try {
                    PoolElement poolElement = taskQueue.elementAt(0);
                    // block (forever) until a worker is available
                    ThreadPoolWorker worker = (ThreadPoolWorker) idleWorkers.remove();
                    worker.process(poolElement);
                    taskQueue.removeElementAt(0);
                    if (poolElement.isRunning()) {
                        taskQueue.addElement(poolElement);
                    }
                    if (isNeedWorker()) {
                        idleWorkers.add(worker);
                    }
                } catch (InterruptedException ex) {
                }
            }
        }
    }
}
